﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using AnyGrid.Renderers;

namespace AnyGrid
{
    public static class AnyGridHtmlHelpers
    {
        private static readonly object _gridsKey = new Object();

        private static GridViewOptions DefaultViewOptions = new GridViewOptions
        {
            CurrentPage = 1,
            GridHtmlId = "list",
            Pager = true
        };

        internal static IList<GridViewModel> Grids(HttpContextBase httpContext)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException("httpContext");
            }
            var result = (IList<GridViewModel>)httpContext.Items[_gridsKey];
            if (result == null)
            {
                result = new List<GridViewModel>();
                httpContext.Items.Add(_gridsKey, result);
            }
            return result;
        }

        public static MvcHtmlString Grid(this HtmlHelper helper, GridViewModel model)
        {
            return Grid(helper, model, null, null);
        }

        public static MvcHtmlString Grid(this HtmlHelper helper, GridViewModel model, GridViewOptions options, IDictionary<string, object> htmlAttributes)
        {
            if (helper == null)
            {
                throw new ArgumentNullException("helper");
            }
            if (model == null)
            {
                throw new ArgumentNullException("model");
            }

            options = options ?? DefaultViewOptions;
            ValidateGridViewModel(model);

            SetGridContext(helper, model, options);
            var gridHtml = options.Renderer.RenderHtml(model, htmlAttributes);
            Grids(helper.ViewContext.HttpContext).Add(model);

            return MvcHtmlString.Create(gridHtml);
        }

        public static MvcHtmlString GridScriptTag(this HtmlHelper helper)
        {
            return GridScriptTag(helper, null);
        }

        public static MvcHtmlString GridScriptTag(this HtmlHelper helper, ViewOptions options)
        {
            if (helper == null)
            {
                throw new ArgumentNullException("helper");
            }
            var g = Grids(helper.ViewContext.HttpContext);
            if (!g.Any())
            {
                return MvcHtmlString.Empty;
            }
            var grids = Grids(helper.ViewContext.HttpContext);
            var script = BaseGridRenderer.RenderJavaScript(grids, options);
            return MvcHtmlString.Create(script);
        }

        private static GridViewModel SetGridContext(this HtmlHelper helper, GridViewModel model, GridViewOptions options)
        {
            var url = new UrlHelper(helper.ViewContext.RequestContext);
            var currentActionName = helper.ViewContext.RouteData.Values["action"].ToString();
            var actionName = model.GetGridDataActionRouteValue(currentActionName);
            model.GridContext = new GridContext
            {
                DataUrl = url.Action(actionName, model.GridDataController, model.GridDataRouteValues),
                HtmlHelper = helper,
                MetadataProvider = ModelMetadataProviders.Current, 
                RowModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, model.RowViewModelType),
                ViewOptions = options
            };
            if (string.IsNullOrEmpty(model.GridContext.ViewOptions.GridHtmlId))
            {
                model.GridContext.ViewOptions.GridHtmlId = helper.ViewData.TemplateInfo.GetFullHtmlFieldId(null);
            }
            return model;
        }

        private static void ValidateGridViewModel(GridViewModel model)
        {
            if (model.RowViewModelType == null)
            {
                throw new ArgumentException("GridViewModel.RowViewModelType is required to be non-null.");
            }
        }
    }
}
